package spider.impl.novel;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import spider.NovelSiteEnum;
import spider.entitys.Novel;
import spider.impl.AbstractSpider;
import spider.interfaces.INovelSpider;
import spider.util.NovelSpiderUtil;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 抽象的小说列表抓取,实现解析tr元素
 * created by yb
 * on 2017/8/14.
 **/
abstract class AbstractNovleSpider extends AbstractSpider implements INovelSpider {
    Element nextPageElement = null;
    protected String nextPage = "";  //下一页的rul

    /**
     * @param url 有小说列表的url
     * @return 所有的小说信息,
     * @throws Exception 目前不支持从这个网站抓取所有的小说信息
     */
    Elements getsTr( String url ) throws Exception {
        return getsTr( url, INovelSpider.MAX_TRY_TIMES );
    }

    protected Elements getsTr( String url, Integer maxTryTimes ) throws Exception {
        if ( maxTryTimes == null ) maxTryTimes = INovelSpider.MAX_TRY_TIMES;
        Elements trs = null;
        for ( int i = 0; i < maxTryTimes; i++ ) {
            try {
                String result = super.craw( url ,"chapter-detail-charset");
                Map< String, String > context = NovelSpiderUtil.getContext( NovelSiteEnum.getNovelSiteEnumByUrl( url ) );
                String novelSelector = context.get( "novel-selector" );
                if ( novelSelector == null )
                    throw new RuntimeException( "url:" + NovelSiteEnum.getNovelSiteEnumByUrl( url ).getUrl() + "目前不支持抓取小说列表" );
                Document doc = Jsoup.parse( result );
                doc.setBaseUri( url );
                String nextPageSelect = context.get( "novel-next-page-select" );
                if ( nextPageSelect != null ) {
                    nextPageElement = doc.select( nextPageSelect ).first();
                    nextPage = nextPageElement != null ? nextPageElement.absUrl( "href" ) : "";

                }
                return doc.select( novelSelector );
            } catch ( Exception e ) {
                System.out.println( url + "尝试第" + i + "次失败" );
            }
        }
        System.out.println( url + "下载" + maxTryTimes + "次依然失败" );
//        throw new RuntimeException( url + "下载" + maxTryTimes + "次依然失败" );
        return null;
    }

    @Override
    public boolean hasNext() {
        return !nextPage.isEmpty();
    }

    @Override
    public String next() {
        return nextPage;
    }

    @Override
    public Iterator< List< Novel > > iterator( String firstPage, Integer maxTryTimes ) {

        nextPage = firstPage;
        return new NovelIterator( maxTryTimes );
    }

    /**
     * 一个迭代器,专门用于对网站小说列表抓取
     */
    private class NovelIterator implements Iterator< List< Novel > > {
        private Integer maxTryTimes;

        public NovelIterator( Integer maxTryTimes ) {
            this.maxTryTimes = maxTryTimes;
        }

        /**
         * Returns {@code true} if the iteration has more elements.
         * (In other words, returns {@code true} if {@link #next} would
         * return an element rather than throwing an exception.)
         *
         * @return {@code true} if the iteration has more elements
         */
        @Override
        public boolean hasNext() {
            return AbstractNovleSpider.this.hasNext();
        }

        /**
         * Returns the next element in the iteration.
         *
         * @return the next element in the iteration
         */
        @Override
        public List< Novel > next() {
            return getsNovel( nextPage, maxTryTimes );
        }
    }
}
